#include "histogram.hxx"
#include <algorithm>

std::ostream& operator<<(std::ostream& output, const Histogram::Type& t) {
    output << "default";
    return output;
}

std::ostream& operator<<(std::ostream& output, const Histogram& histogram) {
    output << "Histogram for type: " << histogram._type << " with " << histogram._binCoint << " bins\n";
    return output;
}

struct interval {
    unsigned int left, right;
};

struct bin {
    int idx;
    unsigned int value;
};

int compare(bin b1, bin b2)
{
    return b1.value > b2.value;
}

int only_start(interval i)
{
    return i.left;
}

int compare_acs(interval b1, interval b2)
{
    return b1.left < b2.left;
}

bool unic(interval b1, interval b2)
{
    return (b1.left == b2.left && b1.right == b2.right);
}

std::vector<int> Histogram::classify(double tr_tr)
{
    unsigned int* histogram = _bins;
    
    bin* hist = new bin[_binCoint];
    for(int i = 0 ; i < _binCoint; i++)
    {
        hist[i].idx = i;
        hist[i].value = histogram[i];
    }

    std::sort(hist, hist + _binCoint, compare);
    std::vector<interval> vals;

    int i = 0;
    while(i < _binCoint)
    {
        bin current = hist[i];
        int left = current.idx -1, right = current.idx +1;

        while(left >= 0 && histogram[left-1] < histogram[left])left--;
        while(right < _binCoint && histogram[right+1] < histogram[right])right++;

        double sum = 0.0;
        for(int s = left; s < right;s++)
        {
            sum += histogram[s];
        }

        double peak = (1 - (histogram[left]+histogram[right])/(2.0*(current.value+0.0000001)))
            *(1 - sum/((histogram[right]-histogram[left]+0.0001)*current.value));

        if(peak > tr_tr || peak < -tr_tr)
        {
            interval i = {left,right};
            vals.push_back(i);
        }else
        {
            break;
        }
        i++;
    }

    std::sort(vals.begin(),vals.end(),compare_acs);
    std::vector<interval> bounds(vals.begin(),std::unique(vals.begin(),vals.end(),unic));
    std::vector<int> result(bounds.size());
    std::transform(bounds.begin(),bounds.end(),result.begin(),only_start);
    
//#if (_DEBUG)
    std::cout << "Histogram thresholds:" << std::endl;
    for (int i = 0; i < result.size()-1; i++)
        std::cout << result[i] << " - "  << result[i+1] << std::endl;
//#endif

    return result;
}
